package org.will.http;

import org.will.http.config.CBHttpHandlerConfig;
import org.will.http.domain.CBHttpConfig;
import org.will.http.domain.CBHttpProxy;
import org.will.http.service.ICBHttpHandler;
import org.will.http.service.impl.CBDefaultHttpHander;
import org.slf4j.Logger;

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @Author wangwei-ww
 * @Date 2017/3/29 20:11
 * @Comment
 */
public final class CBHttpBootStrap {
    private Logger logger = CBHttpLogFactory.getLogger();
    private AtomicBoolean bootStrapped = new AtomicBoolean(false);
    private CBHttpHandlerConfig config = null;

    public CBHttpBootStrap(CBHttpHandlerConfig config) {
        this.config = config;
        bootstrap();
    }

    private final void bootstrap() {
        if (bootStrapped.compareAndSet(false, true)) {
            doBootStrap();
        }
    }

    /**
     * [1] 根据proxy配置初始化httphandler
     * [2] 根据策略选择，开启选择器
     */
    private final void doBootStrap() {
        initHttpHandlers();
        initMeasureTimer();
    }

    /**
     * [1] 配置代理handler初始化
     * [2] 直连handler初始化
     */
    private void initHttpHandlers() {
        for (CBHttpProxy proxy : config.parseProxyConfg()) {
            CBHttpConfig config = new CBHttpConfig();
            config.setProxy(proxy);
            buildDefaultHttpHandler(config);
        }
        CBHttpConfig config = new CBHttpConfig();
        buildDefaultHttpHandler(config);
    }

    private void initMeasureTimer() {
        if (!config.isAutoMeasure()) {
            return;
        }
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                for (ICBHttpHandler handler : CBHttpHandlerManager.getAllHttpHandler()) {
                    measureResponseCost(handler);
                }
            }
        }, 10, config.getMeasureInterval());
    }

    private void buildDefaultHttpHandler(CBHttpConfig config) {
        ICBHttpHandler handler = null;
        try {
            handler = new CBDefaultHttpHander(config);
        } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
            logger.error("[CBHttpBootStrap] INIT httpHandler err", e);
        }
        if (handler != null) {
            CBHttpHandlerManager.addHttpHandler(handler);
            finishBuildHttpHandler(config);
        }
    }

    private void finishBuildHttpHandler(CBHttpConfig config) {
        String sep = "\n";
        StringBuilder sb = new StringBuilder();
        sb.append(sep);
        sb.append("#--------------CBHttpConfig--------------#").append(sep);
        sb.append("# connectionTimeOut = ").append(config.getConnectionTimeout()).append(sep);
        sb.append("# readTimeOut = ").append(config.getReadTimeout()).append(sep);
        sb.append("# proxy = ").append(config.getProxy()).append(sep);
        if (config.getProxy() != null) {
            sb.append("# proxyHost = ").append(config.getProxy().getHost()).append(sep);
            sb.append("# proxyPort = ").append(config.getProxy().getPort()).append(sep);
        }
        sb.append("#----------------------------------------#").append(sep);
        logger.info(sb.toString());
    }

    private void measureResponseCost(ICBHttpHandler handler) {
        long start = System.currentTimeMillis();
        try {
            handler.get(config.getMeasureURL(), null);
        } catch (Exception e) {
            logger.error("[CBHttpBootStrap] proxy:{} measureResponseCost err ", handler.getHttpConfig().getProxy(), e);
            handler.setMeasureCost(Long.MAX_VALUE);
            return;
        }
        long cost = System.currentTimeMillis() - start;
        handler.setMeasureCost(cost);
        logger.info("[CBHttpBootStrap] proxy:{} measureResponseCost cost {}ms", handler.getHttpConfig().getProxy(), cost);
    }


}

